home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 176-200 / disk_195 / microemacs / src.zoo / unix.c < prev    next >
C/C++ Source or Header  |  1989-03-23  |  14KB  |  609 lines

  1. /*    UNIX.C:    Operating specific I/O and Spawning functions
  2.         under UNIX V7, BSD4.2/3, System V, SUN OS and SCO XENIX
  3.         for MicroEMACS 3.10
  4.         (C)opyright 1988 by Daniel M. Lawrence
  5. */
  6.  
  7. #include        <stdio.h>
  8. #include    "estruct.h"
  9. #include    "etype.h"
  10. #if    V7 | BSD | USG | HPUX | SUN | XENIX
  11. #include        "edef.h"
  12. #include    "elang.h"
  13.  
  14. #if    USG | HPUX | SUN | XENIX            /* System V */
  15. #include    <signal.h>
  16. #include    <termio.h>
  17. #include    <fcntl.h>
  18. #include    <ndir.h>
  19. int kbdflgs;            /* saved keyboard fd flags    */
  20. int kbdpoll;            /* in O_NDELAY mode            */
  21. int kbdqp;            /* there is a char in kbdq    */
  22. char kbdq;            /* char we've already read    */
  23. struct    termio    otermio;    /* original terminal characteristics */
  24. struct    termio    ntermio;    /* charactoristics to use inside */
  25. #endif
  26.  
  27. #if V7 | BSD
  28. /* I hit a system name here... we have to define it back to what
  29.    emacs expacts */
  30. #undef    CTRL
  31. #include        <sgtty.h>        /* for stty/gtty functions */
  32. #include    <signal.h>
  33. #include    <sys/types.h>
  34. #include    <sys/dir.h>
  35. #include    <sys/stat.h>
  36. struct  sgttyb  ostate;          /* saved tty state */
  37. struct  sgttyb  nstate;          /* values for editor mode */
  38. struct tchars    otchars;    /* Saved terminal special character set */
  39. struct tchars    ntchars = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  40. #undef    CTRL
  41. #define CTRL    0x0100        /* Control flag, or'ed in        */
  42.  
  43. #if BSD
  44. #include <sys/ioctl.h>        /* to get at the typeahead */
  45. extern    int rtfrmshell();    /* return from suspended shell */
  46. #define    TBUFSIZ    128
  47. char tobuf[TBUFSIZ];        /* terminal output buffer */
  48. #endif
  49. #endif
  50.  
  51. #if     V7 | USG | HPUX | SUN | XENIX | BSD
  52. #include        <signal.h>
  53. extern int vttidy();
  54. #endif
  55.  
  56. /*
  57.  * This function is called once to set up the terminal device streams.
  58.  * On VMS, it translates TT until it finds the terminal, then assigns
  59.  * a channel to it and sets it raw. On CPM it is a no-op.
  60.  */
  61. ttopen()
  62.  
  63. {
  64. #if    USG | HPUX | SUN | XENIX
  65.     ioctl(0, TCGETA, &otermio);    /* save old settings */
  66.     ntermio.c_iflag = 0;        /* setup new settings */
  67.     ntermio.c_oflag = 0;
  68.     ntermio.c_cflag = otermio.c_cflag;
  69.     ntermio.c_lflag = 0;
  70.     ntermio.c_line = otermio.c_line;
  71.     ntermio.c_cc[VMIN] = 1;
  72.     ntermio.c_cc[VTIME] = 0;
  73.     ioctl(0, TCSETAW, &ntermio);    /* and activate them */
  74.     kbdflgs = fcntl( 0, F_GETFL, 0 );
  75.     kbdpoll = FALSE;
  76. #endif
  77.  
  78. #if     V7 | BSD
  79.         gtty(0, &ostate);                       /* save old state */
  80.         gtty(0, &nstate);                       /* get base of new state */
  81.         nstate.sg_flags |= RAW;
  82.         nstate.sg_flags &= ~(ECHO|CRMOD);       /* no echo for now... */
  83.         stty(0, &nstate);                       /* set mode */
  84.     ioctl(0, TIOCGETC, &otchars);        /* Save old characters */
  85.     ioctl(0, TIOCSETC, &ntchars);        /* Place new character into K */
  86. #if    BSD
  87.     /* provide a smaller terminal output buffer so that
  88.        the type ahead detection works better (more often) */
  89.     setbuffer(stdout, &tobuf[0], TBUFSIZ);
  90.     signal(SIGTSTP,SIG_DFL);    /* set signals so that we can */
  91.     signal(SIGCONT,rtfrmshell);    /* suspend & restart emacs */
  92. #endif
  93. #endif
  94.     /* on all screens we are not sure of the initial position
  95.        of the cursor                    */
  96.     ttrow = 999;
  97.     ttcol = 999;
  98. }
  99.  
  100. /*
  101.  * This function gets called just before we go back home to the command
  102.  * interpreter.
  103.  */
  104.  
  105. ttclose()
  106.  
  107. {
  108. #if    USG | HPUX | SUN | XENIX
  109.     ioctl(0, TCSETA, &otermio);    /* restore terminal settings */
  110.     fcntl(0, F_SETFL, kbdflgs);
  111. #endif
  112.  
  113. #if     V7 | BSD
  114.         stty(0, &ostate);
  115.     ioctl(0, TIOCSETC, &otchars);    /* Place old character into K */
  116. #endif
  117. }
  118.  
  119. /*
  120.  * Write a character to the display. On VMS, terminal output is buffered, and
  121.  * we just put the characters in the big array, after checking for overflow.
  122.  * On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
  123.  * MS-DOS (use the very very raw console output routine).
  124.  */
  125. ttputc(c)
  126. {
  127. #if     V7 | USG | HPUX | SUN | XENIX | BSD
  128.         fputc(c, stdout);
  129. #endif
  130. }
  131.  
  132. /*
  133.  * Flush terminal buffer. Does real work where the terminal output is buffered
  134.  * up. A no-operation on systems where byte at a time terminal I/O is done.
  135.  */
  136. ttflush()
  137. {
  138. #if     V7 | USG | HPUX | SUN | XENIX | BSD
  139.         fflush(stdout);
  140. #endif
  141. }
  142.  
  143. /*    TTGETC:    Read a character from the terminal, performing no
  144.         editing and doing no echo at all. More complex in VMS
  145.         that almost anyplace else, which figures. Very simple
  146.         on CPM, because the system can do exactly what you
  147.         want.
  148. */
  149.  
  150. ttgetc()
  151.  
  152. {
  153. #if     V7 | BSD
  154.     char c;
  155.  
  156.         read(0, &c, 1);
  157.     return(255 & (int)c);
  158. #endif
  159.  
  160. #if    USG | HPUX | SUN | XENIX
  161.     if (kbdqp)
  162.         kbdqp = FALSE;
  163.     else {
  164.         /* we desperatly seek a character so we turn off
  165.            the NO_DELAY flag and simply wait for the bastard*/
  166.         if (fcntl(0, F_SETFL, kbdflgs) < 0 && kbdpoll)
  167.             return(FALSE);
  168.         kbdpoll = FALSE;    /* no polling */
  169.         read(0, &kbdq, 1);    /* wait until we get a character */
  170.     }
  171.     return(kbdq & 255);
  172. #endif
  173. }
  174.  
  175. #if    TERMCAP & (USG | HPUX | SUN | XENIX)
  176. /* get a character with timeout */
  177. mttgetc()
  178.  
  179. {
  180.     struct termio tset;
  181.     int status;
  182.     char c,c_eof,c_eol;
  183.     int i,count;
  184.     long trns;
  185.  
  186.     fcntl(0,F_SETFL,O_NDELAY);
  187.     for(count=150; count != 0 ; --count) {
  188.         i = read(0,&c,1);         /* get a character */
  189.         if (i == 1)            /* got a char */
  190.             break;
  191.     }
  192.     fcntl(0,F_SETFL,0);
  193.     if (i<= 0)    /* timeout error */
  194.         return(-1);
  195.     i = c;
  196.     return(i & 0xff);        /* return character */
  197. }
  198. #endif
  199.  
  200. #if    TYPEAH
  201. /* typahead:    Check to see if any characters are already in the
  202.         keyboard buffer
  203. */
  204.  
  205. typahead()
  206.  
  207. {
  208. #if    BSD
  209.     int x;    /* holds # of pending chars */
  210.  
  211.     return((ioctl(0,FIONREAD,&x) < 0) ? 0 : x);
  212. #endif
  213.  
  214. #if    USG | HPUX | SUN | XENIX
  215.     if (!kbdqp) {
  216.         /* set O_NDELAY */
  217.         if (fcntl(0, F_SETFL, kbdflgs | O_NDELAY) < 0 && kbdpoll)
  218.             return(FALSE);
  219.         kbdpoll = TRUE;
  220.         kbdqp = (1 == read(0, ëbdq, 1));
  221.     }
  222.     return(kbdqp);
  223. #endif
  224. #if    V7
  225.     return(FALSE);
  226. #endif
  227. }
  228. #endif
  229.  
  230. /*
  231.  * Create a subjob with a copy of the command intrepreter in it. When the
  232.  * command interpreter exits, mark the screen as garbage so that you do a full
  233.  * repaint. Bound to "^X C". The message at the start in VMS puts out a newline.
  234.  * Under some (unknown) condition, you don't get one free when DCL starts up.
  235.  */
  236. spawncli(f, n)
  237. {
  238.         register char *cp;
  239.         char    *getenv();
  240.  
  241.     /* don't allow this command if restricted */
  242.     if (restflag)
  243.         return(resterr());
  244.  
  245.         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  246.         TTflush();
  247.         TTclose();                              /* stty to old settings */
  248.         if ((cp = getenv("SHELL")) != NULL && *cp != '\0')
  249.                 system(cp);
  250.         else
  251. #if    BSD
  252.                 system("exec /bin/csh");
  253. #else
  254.                 system("exec /bin/sh");
  255. #endif
  256.         sgarbf = TRUE;
  257.     sleep(2);
  258.         TTopen();
  259.         return(TRUE);
  260. }
  261.  
  262. #if    BSD
  263.  
  264. bktoshell()        /* suspend MicroEMACS and wait to wake up */
  265. {
  266.     int pid;
  267.  
  268.     vttidy();
  269.     pid = getpid();
  270.     kill(pid,SIGTSTP);
  271. }
  272.  
  273. rtfrmshell()
  274. {
  275.     TTopen();
  276.     curwp->w_flag = WFHARD;
  277.     sgarbf = TRUE;
  278. }
  279. #endif
  280.  
  281. /*
  282.  * Run a one-liner in a subjob. When the command returns, wait for a single
  283.  * character to be typed, then mark the screen as garbage so a full repaint is
  284.  * done. Bound to "C-X !".
  285.  */
  286. spawn(f, n)
  287. {
  288.         register int    s;
  289.         char            line[NLINE];
  290.  
  291.     /* don't allow this command if restricted */
  292.     if (restflag)
  293.         return(resterr());
  294.  
  295.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  296.                 return(s);
  297.         TTputc('\n');                /* Already have '\r'    */
  298.         TTflush();
  299.         TTclose();                              /* stty to old modes    */
  300.         system(line);
  301.         TTopen();
  302.         TTflush();
  303.     /* if we are interactive, pause here */
  304.     if (clexec == FALSE) {
  305.             mlputs(TEXT6);
  306. /*                     "\r\n\n[End]" */
  307.             tgetc();
  308.         }
  309.         sgarbf = TRUE;
  310.         return(TRUE);
  311. }
  312.  
  313. /*
  314.  * Run an external program with arguments. When it returns, wait for a single
  315.  * character to be typed, then mark the screen as garbage so a full repaint is
  316.  * done. Bound to "C-X $".
  317.  */
  318.  
  319. execprg(f, n)
  320.  
  321. {
  322.         register int    s;
  323.         char            line[NLINE];
  324.  
  325.     /* don't allow this command if restricted */
  326.     if (restflag)
  327.         return(resterr());
  328.  
  329.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  330.                 return(s);
  331.         TTputc('\n');                /* Already have '\r'    */
  332.         TTflush();
  333.         TTclose();                              /* stty to old modes    */
  334.         system(line);
  335.         TTopen();
  336.         mlputs(TEXT188);                        /* Pause.               */
  337. /*             "[End]" */
  338.         TTflush();
  339.         while ((s = tgetc()) != '\r' && s != ' ')
  340.                 ;
  341.         sgarbf = TRUE;
  342.         return(TRUE);
  343. }
  344.  
  345. /*
  346.  * Pipe a one line command into a window
  347.  * Bound to ^X @
  348.  */
  349. pipecmd(f, n)
  350. {
  351.         register int    s;    /* return status from CLI */
  352.     register WINDOW *wp;    /* pointer to new window */
  353.     register BUFFER *bp;    /* pointer to buffer to zot */
  354.         char    line[NLINE];    /* command line send to shell */
  355.     static char bname[] = "command";
  356.  
  357.     static char filnam[NFILEN] = "command";
  358.  
  359.     /* don't allow this command if restricted */
  360.     if (restflag)
  361.         return(resterr());
  362.  
  363.     /* get the command to pipe in */
  364.         if ((s=mlreply("@", line, NLINE)) != TRUE)
  365.                 return(s);
  366.  
  367.     /* get rid of the command output buffer if it exists */
  368.         if ((bp=bfind(bname, FALSE, 0)) != FALSE) {
  369.         /* try to make sure we are off screen */
  370.         wp = wheadp;
  371.         while (wp != NULL) {
  372.             if (wp->w_bufp == bp) {
  373.                 onlywind(FALSE, 1);
  374.                 break;
  375.             }
  376.             wp = wp->w_wndp;
  377.         }
  378.         if (zotbuf(bp) != TRUE)
  379.  
  380.             return(FALSE);
  381.     }
  382.  
  383.         TTputc('\n');                /* Already have '\r'    */
  384.         TTflush();
  385.         TTclose();                              /* stty to old modes    */
  386.     strcat(line,">");
  387.     strcat(line,filnam);
  388.         system(line);
  389.         TTopen();
  390.         TTflush();
  391.         sgarbf = TRUE;
  392.         s = TRUE;
  393.  
  394.     if (s != TRUE)
  395.         return(s);
  396.  
  397.     /* split the current window to make room for the command output */
  398.     if (splitwind(FALSE, 1) == FALSE)
  399.             return(FALSE);
  400.  
  401.     /* and read the stuff in */
  402.     if (getfile(filnam, FALSE) == FALSE)
  403.         return(FALSE);
  404.  
  405.     /* make this window in VIEW mode, update all mode lines */
  406.     curwp->w_bufp->b_mode |= MDVIEW;
  407.     wp = wheadp;
  408.     while (wp != NULL) {
  409.         wp->w_flag |= WFMODE;
  410.         wp = wp->w_wndp;
  411.     }
  412.  
  413.     /* and get rid of the temporary file */
  414.     unlink(filnam);
  415.     return(TRUE);
  416. }
  417.  
  418. rename(old, new)    /* change the name of a file */
  419.  
  420. char *old;    /* original file name */
  421. char *new;    /* new file name */
  422.  
  423. {
  424.     link(old, new);
  425.     unlink(old);
  426. }
  427.  
  428. /*
  429.  * filter a buffer through an external DOS program
  430.  * Bound to ^X #
  431.  */
  432. filter(f, n)
  433.  
  434. {
  435.         register int    s;    /* return status from CLI */
  436.     register BUFFER *bp;    /* pointer to buffer to zot */
  437.         char line[NLINE];    /* command line send to shell */
  438.     char tmpnam[NFILEN];    /* place to store real file name */
  439.     static char bname1[] = "fltinp";
  440.  
  441.     static char filnam1[] = "fltinp";
  442.     static char filnam2[] = "fltout";
  443.  
  444.     /* don't allow this command if restricted */
  445.     if (restflag)
  446.         return(resterr());
  447.  
  448.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  449.         return(rdonly());    /* we are in read only mode    */
  450.  
  451.     /* get the filter name and its args */
  452.         if ((s=mlreply("#", line, NLINE)) != TRUE)
  453.                 return(s);
  454.  
  455.     /* setup the proper file names */
  456.     bp = curbp;
  457.     strcpy(tmpnam, bp->b_fname);    /* save the original name */
  458.     strcpy(bp->b_fname, bname1);    /* set it to our new one */
  459.  
  460.     /* write it out, checking for errors */
  461.     if (writeout(filnam1) != TRUE) {
  462.         mlwrite(TEXT2);
  463. /*                      "[Cannot write filter file]" */
  464.         strcpy(bp->b_fname, tmpnam);
  465.         return(FALSE);
  466.     }
  467.  
  468.         TTputc('\n');                /* Already have '\r'    */
  469.         TTflush();
  470.         TTclose();                              /* stty to old modes    */
  471.     strcat(line," <fltinp >fltout");
  472.         system(line);
  473.         TTopen();
  474.         TTflush();
  475.         sgarbf = TRUE;
  476.         s = TRUE;
  477.  
  478.     /* on failure, escape gracefully */
  479.     if (s != TRUE || (readin(filnam2,FALSE) == FALSE)) {
  480.         mlwrite(TEXT3);
  481. /*                      "[Execution failed]" */
  482.         strcpy(bp->b_fname, tmpnam);
  483.         unlink(filnam1);
  484.         unlink(filnam2);
  485.         return(s);
  486.     }
  487.  
  488.     /* reset file name */
  489.     strcpy(bp->b_fname, tmpnam);    /* restore name */
  490.     bp->b_flag |= BFCHG;        /* flag it as changed */
  491.  
  492.     /* and get rid of the temporary file */
  493.     unlink(filnam1);
  494.     unlink(filnam2);
  495.     return(TRUE);
  496. }
  497.  
  498. /* return a system dependant string with the current time */
  499.  
  500. char *PASCAL NEAR timeset()
  501.  
  502. {
  503.     register char *sp;    /* temp string pointer */
  504.     char buf[16];        /* time data buffer */
  505.     extern char *ctime();
  506.  
  507.     time(buf);
  508.     sp = ctime(buf);
  509.     sp[strlen(sp)-1] = 0;
  510.     return(sp);
  511. }
  512.  
  513. #if    COMPLET
  514. /*    FILE Directory routines        */
  515.  
  516. DIR *dirptr = NULL;    /* pointer to the current directory being searched */
  517.  
  518. char path[NFILEN];    /* path of file to find */
  519. char rbuf[NFILEN];    /* return file buffer */
  520. char *nameptr;        /* ptr past end of path in rbuf */
  521.  
  522. /*    do a wild card directory search (for file name completion) */
  523.  
  524. char *PASCAL NEAR getffile(fspec)
  525.  
  526. char *fspec;    /* pattern to match */
  527.  
  528. {
  529.     register int index;        /* index into various strings */
  530.     register int point;        /* index into other strings */
  531.     register int extflag;        /* does the file have an extention? */
  532.  
  533.     /* first parse the file path off the file spec */
  534.     strcpy(path, fspec);
  535.     index = strlen(path) - 1;
  536.     while (index >= 0 && (path[index] != '/' &&
  537.                 path[index] != '\\' && path[index] != ':'))
  538.         --index;
  539.     path[index+1] = 0;
  540.  
  541.     /* check for an extension */
  542.     point = strlen(fspec) - 1;
  543.     extflag = FALSE;
  544.     while (point >= 0) {
  545.         if (fspec[point] == '.') {
  546.             extflag = TRUE;
  547.             break;
  548.         }
  549.         point--;
  550.     }
  551.  
  552.     /* open the directory pointer */
  553.     if (dirptr != NULL) {
  554.         closedir(dirptr);
  555.         dirptr = NULL;
  556.     }
  557.     dirptr = opendir(path);
  558.     if (dirptr == NULL)
  559.         return(NULL);
  560.  
  561.     strcpy(rbuf, path);
  562.     nameptr = &rbuf[strlen(rbuf)];
  563.  
  564.     /* and call for the first file */
  565.     return(getnfile());
  566. }
  567.  
  568. char *PASCAL NEAR getnfile()
  569.  
  570. {
  571.     register struct direct *dp;    /* directory entry pointer */
  572.     register int index;        /* index into various strings */
  573.     struct stat fstat;
  574.  
  575.     /* and call for the next file */
  576. nxtdir:    dp = readdir(dirptr);
  577.     if (dp == NULL)
  578.         return(NULL);
  579.  
  580.     /* check to make sure we skip directory entries */
  581.     strcpy(nameptr, dp->d_name);
  582.     stat(rbuf, &fstat);
  583.     if ((fstat.st_mode & S_IFMT) != S_IFREG)
  584.         goto nxtdir;
  585.  
  586.     /* return the next file name! */
  587.     return(rbuf);
  588. }
  589. #else
  590. char *PASCAL NEAR getffile(fspec)
  591.  
  592. char *fspec;    /* file to match */
  593.  
  594. {
  595.     return(NULL);
  596. }
  597.  
  598. char *PASCAL NEAR getnfile()
  599.  
  600. {
  601.     return(NULL);
  602. }
  603. #endif
  604. #else
  605. unixhello()
  606. {
  607. }
  608. #endif
  609.